package com.mianyang.zhangsan.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mianyang.zhangsan.common.util.OperationManHelper;
import com.mianyang.zhangsan.common.util.StringUtils;
import com.mianyang.zhangsan.model.dto.SecPaperCorrectDto;
import com.mianyang.zhangsan.model.dto.SecPaperDto;
import com.mianyang.zhangsan.model.dto.SecPracticeDto;
import com.mianyang.zhangsan.model.dto.SecProblemDto;
import com.mianyang.zhangsan.model.dto.SecUserAnswer;
import com.mianyang.zhangsan.model.entity.*;
import com.mianyang.zhangsan.service.*;
import com.mianyang.zhangsan.mapper.SecPaperInstMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
* @author jiangjr
*/
@Service
public class SecPaperInstServiceImpl extends ServiceImpl<SecPaperInstMapper, SecPaperInst>
    implements SecPaperInstService{
    @Autowired
    private SecPaperService paperService;
    @Autowired
    private SecPaperProService paperProService;
    @Autowired
    private SecProblemInstService problemInstService;
    @Autowired
    private SecPaperBankService paperBankService;
    @Autowired
    private SecProblemService problemService;

    @Override
    public SecPracticeDto selectPractice(Long paperId) {
        QueryWrapper<SecPaperInst> wrapper = new QueryWrapper<>();
        if (paperId != null) {
            wrapper.eq("paper_id", paperId);
            List<SecPaperInst> paperInstList = list(wrapper);
            SecPaper paper = paperService.getById(paperId);
            return SecPracticeDto.builder()
                    .paper(paper)
                    .paperInstList(paperInstList).build();
        }
        return null;
    }

    @Override
    public Page<SecPaperInst> selectPracticeByPage(SecPaperInst paper, Integer current, Integer pageSize) {
        QueryWrapper<SecPaperInst> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(paper.getPaperName())) {
            wrapper.like("paper_name", paper.getPaperName());
        }
        if (paper.getIsWin() != null) {
            wrapper.eq("is_win", paper.getIsWin());
        }
        if (paper.getRealScore() != null) {
            wrapper.gt("real_score", paper.getRealScore());
        }
        wrapper.orderByDesc("real_score");
        return page(new Page<>(current, pageSize), wrapper);
    }

    @Override
    public SecPaperDto selectPracticeInfo(Long paperInstId) {
        // 查询试卷实例信息
        SecPaperInst paperInst = getById(paperInstId);
        // 查询试卷信息
        SecPaper paper = paperService.getById(paperInst.getPaperId());
        // 查询问题实例信息
        List<Long> problemIds = paperProService.selectProblemsByPaperInstId(paperInst.getPaperInstId());
        List<SecProblemDto> problems = problemInstService.selectProblems(problemIds);
        return SecPaperDto.builder()
                .paper(paper)
                .paperInst(paperInst)
                .problems(problems).build();
    }

    @Override
    public SecPaperDto practice(Long paperInstId) {
        // 查询试卷实例（已经生成的练习）
        SecPaperInst paperInst = getById(paperInstId);
        paperInst.setPaperInstId(null);
        save(paperInst);
        List<Long> problemIds = paperProService.selectProblemsByPaperInstId(paperInstId);
        List<SecPaperPro> paperPros = new ArrayList<>(problemIds.size());
        for (Long problemId : problemIds) {
            SecPaperPro paperPro = SecPaperPro.builder()
                    .paperInstId(paperInstId)
                    .problemInstId(problemId).build();
            paperPros.add(paperPro);
        }
        paperProService.saveBatch(paperPros);
        // 生成一样的试卷实例
        List<SecProblemInst> problemInstList = problemInstService.listByIds(problemIds);
        problemInstList.forEach(pro -> pro.setUserAnswer(null));
        problemInstService.saveBatch(problemInstList);
        return selectPracticeInfo(paperInst.getPaperInstId());
    }

    @Override
    public SecPaperDto generatorPractice(Long paperId) {
        SecPaper paper = paperService.getById(paperId);
        // 查询试卷和题库引用关系（查询题型和题的数目）
        List<SecPaperBank> paperBanks = paperBankService.selectByPaperId(paper.getPaperId());
        // 根据题型和数目从题库中取出题目
        List<SecProblem> problems = new ArrayList<>(paper.getProblems());
        for (SecPaperBank paperBank : paperBanks) {
            List<SecProblem> list = problemService.selectProblemByRandom(paperBank.getBankId(),
                    paperBank.getProblems(),
                    paperBank.getProblemType());
            problems.addAll(list);
        }
        // 生成试卷实例
        SecPaperInst paperInst = SecPaperInst.builder()
                .paperName(paper.getPaperName())
                .paperId(paper.getPaperId()).build();
        save(paperInst);
        // 生成问题实例
        List<SecProblemInst> problemInstList = new ArrayList<>(problems.size());
        for (SecProblem problem : problems) {
            SecProblemInst problemInst = SecProblemInst.builder()
                    .problemId(problem.getProblemId())
                    .problemDesc(problem.getProblemDesc())
                    .problemType(problem.getProblemType())
                    .problemRight(problem.getProblemRight())
                    .analysis(problem.getAnalysis())
                    .bankId(problem.getBankId())
                    .bankName(problem.getBankName()).build();
            problemInstList.add(problemInst);
        }
        problemInstService.saveBatch(problemInstList);
        // 建立关系
        List<SecPaperPro> paperPros = new ArrayList<>(problemInstList.size());
        for (SecProblemInst problemInst : problemInstList) {
            SecPaperPro secPaperPro = SecPaperPro.builder()
                    .paperInstId(paperInst.getPaperInstId())
                    .problemInstId(problemInst.getProblemInstId()).build();
            paperPros.add(secPaperPro);
        }
        paperProService.saveBatch(paperPros);
        return selectPracticeInfo(paperInst.getPaperInstId());
    }

    @Override
    public List<SecPaperInst> selectPaperOrderBy(String column, int top) {
        QueryWrapper<SecPaperInst> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(column)) {
            wrapper.orderBy(true, false, column);
            return page(new Page<>(0, top), wrapper).getRecords();
        }
        return null;
    }

    @Override
    public int correct(SecUserAnswer userAnswer) {
        int score = 0;
        // 查询试卷实例信息
        Long paperInstId = userAnswer.getPaperInstId();
        SecPaperDto paper = selectPracticeInfo(paperInstId);
        // 检查试卷
        List<SecProblemDto> problems = paper.getProblems();
        if (StringUtils.isNotEmpty(userAnswer.getUserAnswer())) {
            JSONArray array = JSONObject.parseArray(userAnswer.getUserAnswer());
            for (Object answer : array) {
                JSONObject jsonAnswer = null;
                if (answer instanceof JSONArray) {
                    jsonAnswer = JSONObject.parseObject(((JSONArray)answer).get(0).toString());
                }
                if (jsonAnswer == null) {
                    return score;
                }
                if (jsonAnswer.containsKey("problemInstId")) {
                    Long problemInstId = jsonAnswer.getLong("problemInstId");
                    Optional<SecProblemDto> currentProblem = problems.stream()
                            .filter(problem -> problem.getProblem().getProblemInstId().equals(problemInstId))
                            .findFirst();
                    if (currentProblem.isPresent()) {
                        SecProblemDto problem = currentProblem.get();
                        // 检查用户答案是否正确
                        if (jsonAnswer.containsKey("userAnswer")) {
                            int currentScore = problem.computeUserAnswer(jsonAnswer.getJSONArray("userAnswer"));
                            //
                            score += currentScore;
                        }
                        // 更新用户答案
                    }
                }
            }
        }
        List<SecProblemInst> problemInsts = problems.stream().map(SecProblemDto::getProblem).collect(Collectors.toList());
        // 更新问题实例
        problemInstService.updateBatchById(problemInsts);
        // 更新试卷实例
        int winScore = paper.getPaper().getWinScore();
        int win = 0;
        if (winScore < score) {
            win = 1;
        }
        SecPaperInst paperInst = paper.getPaperInst();
        paperInst.setIsWin(win);
        paperInst.setAccountId(OperationManHelper.getAccountId());
        paperInst.setAccountName(OperationManHelper.getAccountName());
        paperInst.setRealTime(userAnswer.getUseTime());
        paperInst.setRealScore(score);
        updateById(paperInst);
        return score;
    }

    @Override
    public void deleteAndPaperInst(Long paperId) {
        // 删除试卷信息
        paperService.removeById(paperId);
        // 删除试卷的实例信息
        QueryWrapper<SecPaperInst> wrapper = new QueryWrapper<>();
        wrapper.eq("paper_id", paperId);
        remove(wrapper);

    }
}




